<script lang="ts" setup>
import { ref, onMounted, computed, watch, nextTick } from 'vue';
import { ElMessage } from 'element-plus';
import tinymce from 'tinymce';
import Editor from '@tinymce/tinymce-vue';

import 'tinymce/themes/silver/theme.min.js';
import 'tinymce/icons/default/icons';
import 'tinymce/plugins/image';
import 'tinymce/plugins/link';
import 'tinymce/plugins/code';
import 'tinymce/plugins/codesample';
import 'tinymce/plugins/table';
import 'tinymce/plugins/lists';
import 'tinymce/plugins/wordcount';
import 'tinymce/plugins/media';
import 'tinymce/plugins/emoticons';
import 'tinymce/plugins/fullscreen';
import 'tinymce/plugins/preview';
import 'tinymce/plugins/pagebreak';
import 'tinymce/plugins/insertdatetime';
import 'tinymce/plugins/hr';
import 'tinymce/plugins/paste';
import 'tinymce/plugins/print';

import { uploadFile2 } from '@/api/common';

interface PropsConfig {
    value: string;
    id?: string;
    config?: any;
    isOss?: boolean;
}

const props = withDefaults(defineProps<PropsConfig>(), {
    value: '',
    id: 'tinymce',
    config: {},
    isOss: false
});

const emit = defineEmits(['update:value']);

const content = ref(props.value);
const editorConfig = {
    selector: '#' + props.id,
    language_url: '/tinymce/langs/zh_CN.js',
    language: 'zh_CN',
    skin_url: '/tinymce/skins/ui/oxide',
    height: 400,
    min_height: 20,
    branding: false,
    // image
    plugins:
        'image link lists print codesample code table wordcount media table fullscreen preview pagebreak insertdatetime hr paste', // 插件
    toolbar:
        'image codesample bold italic underline alignleft aligncenter alignright alignjustify | forecolor backcolor | fontselect | fontsizeselect | formatselect |  bullist numlist | outdent indent blockquote | removeformat| undo redo | link unlink media insertdatetime table  hr pagebreak | fullscreen preview | strikethrough', // 工具条
    font_formats: 'Arial=arial,helvetica,sans-serif; 宋体=SimSun;  微软雅黑=Microsoft Yahei; Impact=impact,chicago;', // 字体
    fontsize_formats: '11px 12px 14px 16px 18px 24px 36px 48px 64px 72px', // 文字大小
    paste_data_images: true,
    codesample_languages: [
        { text: 'HTML/XML', value: 'markup' },
        { text: 'JavaScript', value: 'javascript' },
        { text: 'CSS', value: 'css' },
        { text: 'Java', value: 'java' },
        { text: 'C++', value: 'cpp' }
    ],
    // 图片上传回调
    images_upload_handler: (blobInfo: any, success: (res: any) => any, failure, progress) => {
        const reader = new FileReader();
        const AllowImgFileSize = 2100000; //上传图片最大值(单位字节)（ 2 M = 2097152 B ）超过2M上传失败
        reader.readAsDataURL(blobInfo.blob());
        reader.onload = function () {
            const resBase = String(this.result);
            const imgType = resBase.split(';')[0];
            const delContent = content.value.replace(`<img src="${resBase}" />`, '');
            if (AllowImgFileSize != 0 && AllowImgFileSize < reader.result.length) {
                // ElMessage.error('上传失败，请上传不大于2M的图片！');
                content.value = delContent;
                // document.querySelector('.tox-dialog__busy-spinner').remove() 删除loading
                failure('上传失败，请上传不大于2M的图片！', { remove: true });
                // 清空上传文件值，使可以重新上传同一张图片
                const input = document?.querySelector('.tox-dropzone')?.querySelector('input');
                input && (input.value = '');
                // 也可以通过重置input类型重新上传
                // document.querySelector('.tox-dropzone')?.querySelector('input')?.setAttribute('type', 'text');
                // setTimeout(() => {
                //     document.querySelector('.tox-dropzone')?.querySelector('input')?.setAttribute('type', 'file');
                // }, 0);
            } else {
                //执行上传操作

                const reg = /<img.*?src=[\"|\']?(.*?)[\"|\']?\s.*?>/gi;
                const imgNum = content.value.match(reg) || [];
                // 图片上传张数不限制
                // 是否使用 oss 上传方式上传图片
                if (props.isOss) {
                    const file = new window.File([blobInfo.blob()], blobInfo.filename(), {
                        type: imgType.split(':')[1]
                    });
                    uploadFile2({
                        file,
                        fileName: file.name
                    }).then(res => {
                        success(res.url);
                    });
                } else {
                    success(this.result);
                }
            }
        };
    },
    ...props.config // 覆盖的配置项
};

const setContent = (res: string) => {
    content.value = res;
};

watch(
    () => props.value,
    (value: string) => {
        content.value = value;
    }
);

watch(
    () => content.value,
    (value: string) => {
        emit('update:value', value);
    }
);

onMounted(() => {
    tinymce.init(editorConfig);
    content.value = props.value;
});

defineExpose({
    setContent,
    tinymceEditors: tinymce.editors
});
</script>

<template>
    <editor :id="id" v-model="content" :init="editorConfig"> </editor>
</template>

<style lang="less" scoped></style>
